/**
 * @name 00 mbuf copydata with tainted size
 * @description Calling m_copydata with an untrusted size argument
 *              could cause a buffer overflow.
 * @kind path-problem
 * @problem.severity warning
 * @id apple-xnu/cpp/mbuf-copydata-with-tainted-size
 */

/*
 * This query is explained in detail in this blog post:
 *
 * https://lgtm.com/blog/apple_xnu_icmp_error_CVE-2018-4407
 *
 * It is based on the assumption that the function `m_mtod`, which returns
 * a pointer to the data stored in an `mbuf`, often returns a buffer
 * containing untrusted data.
 *
 * The query has multiple results. The interesting result is the one in
 * `ip_icmp.c`.
 */

import cpp
import semmle.code.cpp.dataflow.TaintTracking
import DataFlow::PathGraph

class Config extends TaintTracking::Configuration {
  Config() { this = "mbuf copydata with tainted size" }

  override predicate isSource(DataFlow::Node source) {
    source.asExpr().(FunctionCall).getTarget().getName() = "m_mtod"
  }

  override predicate isSink(DataFlow::Node sink) {
    exists (FunctionCall call
    | call.getArgument(2) = sink.asExpr() and
      call.getTarget().getName().matches("%copydata"))
  }
}

from Config cfg, DataFlow::PathNode source, DataFlow::PathNode sink
where cfg.hasFlowPath(source, sink)
select sink, source, sink, "m_copydata with tainted size."
